package com.blyat.xsoft.kernel.component.security.oauth2.util;

import com.blyat.xsoft.kernel.util.SM4Util;
import com.google.common.base.Strings;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.oauth2.common.OAuth2AccessToken;
import org.springframework.security.oauth2.provider.authentication.OAuth2AuthenticationDetails;

import javax.servlet.http.HttpServletRequest;
import java.util.Enumeration;

/**
 * @Auther: syh
 * @Date: 2020/7/22
 * @Description:
 */
public class TokenUtil {

    private static final Logger logger = LoggerFactory.getLogger(TokenUtil.class);

    public static Object getInfo(OAuth2AccessToken token, String key) {
        if (token == null || token.getAdditionalInformation() == null) {
            return null;
        }
        return token.getAdditionalInformation().get(key);
    }

    public static <R> R getInfoOrDefault(OAuth2AccessToken token, String key, R defaultValue) {
        return getInfo(token, key) == null ? defaultValue : (R)getInfo(token, key);
    }

    public static String getStringInfo(OAuth2AccessToken token, String key) {
        return getInfo(token, key) == null ? null : getInfo(token, key).toString();
    }

    public static String decryptInfo(OAuth2AccessToken token, String key) {
        String value = getStringInfo(token, key);
        try {
            return Strings.isNullOrEmpty(value) ? null : SM4Util.decryptEcb(value);
        } catch (Exception e) {
            return null;
        }
    }

    public static String getAccessToken(HttpServletRequest request) {
        return extract(request);
    }

    static String extract(HttpServletRequest request) {
        return extractToken(request);
    }

    static String extractToken(HttpServletRequest request) {
        // first check the header...
        String token = extractHeaderToken(request);

        // bearer type allows a request parameter as well
        if (token == null) {
            logger.debug("Token not found in headers. Trying request parameters.");
            token = request.getParameter(OAuth2AccessToken.ACCESS_TOKEN);
            if (token == null) {
                logger.debug("Token not found in request parameters.  Not an OAuth2 request.");
            }
            else {
                request.setAttribute(OAuth2AuthenticationDetails.ACCESS_TOKEN_TYPE, OAuth2AccessToken.BEARER_TYPE);
            }
        }

        return token;
    }

    static String extractHeaderToken(HttpServletRequest request) {
        Enumeration<String> headers = request.getHeaders("Authorization");
        while (headers.hasMoreElements()) { // typically there is only one (most servers enforce that)
            String value = headers.nextElement();
            if ((value.toLowerCase().startsWith(OAuth2AccessToken.BEARER_TYPE.toLowerCase()))) {
                String authHeaderValue = value.substring(OAuth2AccessToken.BEARER_TYPE.length()).trim();
                // Add this here for the auth details later. Would be better to change the signature of this method.
                request.setAttribute(OAuth2AuthenticationDetails.ACCESS_TOKEN_TYPE,
                        value.substring(0, OAuth2AccessToken.BEARER_TYPE.length()).trim());
                int commaIndex = authHeaderValue.indexOf(',');
                if (commaIndex > 0) {
                    authHeaderValue = authHeaderValue.substring(0, commaIndex);
                }
                return authHeaderValue;
            }
        }

        return null;
    }
}
